<template>
  <n-upload
    :file-list="proxyFileList"
    @before-upload="beforeUpload"
    @download="download"
    @remove="remove"
    v-bind="$attrs"
  >
    <template v-if="!$attrs?.directoryDnd">
      <n-button v-if="($attrs?.listType as ListType) !== 'image-card'" :loading="loading">
        上传</n-button
      >
      <n-spin v-else :show="loading"> 上传 </n-spin>
    </template>

    <n-upload-dragger v-else>
      <div style="margin-bottom: 12px">
        <n-icon size="48" :depth="3">
          <archive-icon />
        </n-icon>
      </div>
      <n-text style="font-size: 16px"> 点击或者拖动文件到该区域来上传 </n-text>
      <n-p depth="3" style="margin: 8px 0 0 0">
        请不要上传敏感数据，比如你的银行卡号和密码，信用卡号有效期和安全码
      </n-p>
    </n-upload-dragger>
  </n-upload>
</template>

<script setup lang="ts">
import globalMinioUpload from './utils/minio'
import { basicDownload } from './utils'
import { UploadFileInfo } from 'naive-ui'
import { ListType } from 'naive-ui/es/upload/src/interface'

const props = withDefaults(
  defineProps<{
    fileList: Array<UploadFileInfo>
    size?: number
    isShowProcess?: boolean
  }>(),
  {
    size: 10, // 上传文件限制大小
    isShowProcess: true // 是否显示上传进度
  }
)
const emit = defineEmits<{
  (e: 'update:fileList', val: Array<UploadFileInfo>): void
}>()
const attrs = useAttrs()

const proxyFileList = computed<Array<UploadFileInfo>>({
  get() {
    return props.fileList || []
  },
  set(val: any) {
    emit('update:fileList', val)
  }
})

const loading = ref(false)

function listenUploadProcess(process: number, id: string) {
  const index = proxyFileList.value.findIndex((k) => k.id === id)
  if (props.isShowProcess) {
    proxyFileList.value[index].percentage = process

    // 上传完成，修改状态
    if (process === 100) {
      proxyFileList.value[index].status = 'finished'
    }
  }
}

function beforeUpload(options: { file: UploadFileInfo; fileList: Array<UploadFileInfo> }) {
  loading.value = true
  const {
    file: { file, name }
  } = options
  const { size } = file as File

  // 判断文件类型
  if (attrs?.accept) {
    const suffix = name.substring(name.lastIndexOf('.')).toLowerCase()
    const isMatch = (attrs.accept as string).split(',').includes(suffix)
    if (!isMatch) {
      window.$message.warning(`请上传${attrs.accept}类型的文件`)
      loading.value = false
      return
    }
  }

  // 转换单位
  const limitSize = props.size * 1024 * 1024
  if (size > limitSize) {
    window.$message.warning(`上传文件不能大于${props.size}M`)
    loading.value = false
    return
  }

  // 构造文件
  const obj: UploadFileInfo = {
    id: Date.now().toString(),
    name,
    status: props.isShowProcess ? 'uploading' : 'finished',
    percentage: 0,
    url: ''
  }
  proxyFileList.value.push(obj)
  proxyFileList.value = JSON.parse(JSON.stringify(proxyFileList.value))

  // oss上传
  globalMinioUpload({
    file: options.file,
    id: obj.id,
    callback: listenUploadProcess
  })
    .then((res: any) => {
      const index = proxyFileList.value.findIndex((k) => k.id === res.id)
      console.log(res.url, index, proxyFileList.value)
      if (res?.url) {
        // 上传成功, 赋值地址
        proxyFileList.value[index].url = res.url
      } else {
        proxyFileList.value[index].status = 'error'
      }
      loading.value = false
    })
    .catch(() => {
      loading.value = false
    })
}

function download(file: UploadFileInfo) {
  // 如果url指向的是一个浏览器可以解析的文件比如png，gif，txt，html，pdf文件等，浏览器会默认打开文件，而不是下载,所以这里手动下载
  basicDownload(file.url as string, file.name)
  return false
}

function remove(options: { file: UploadFileInfo; fileList: Array<UploadFileInfo> }) {
  const { file } = options
  const index = proxyFileList.value.findIndex((k) => k.id === file.id)
  proxyFileList.value.splice(index, 1)
}
</script>

<style lang="less" scoped></style>
